<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      const obj = {
        name: '小猪课堂',
        age: 23,
      };
      const proxy = new Proxy(obj, {});

      // apply
      function sum(a, b) {
        return a + b;
      }
      const p1 = new Proxy(sum, {
        /**
         * @param target 源函数
         * @param thisArg 调用的时候的this指向
         * @param args 参数列表
         * **/
        apply(target, thisArg, args) {
          return (args[0] + args[1]) * 100;
        },
      });

      console.log(p1(1, 2)); // 300

      // construct  构造函数拦截
      const p2 = new Proxy(function () {}, {
        /**
         * @param target 源构造函数
         * @param args 参数列表
         * @param newTarget 被调用的构造函数 也就是 下面的p2
         * **/
        construct(target, args, newTarget) {
          return { value: '我是' + args[0] };
        },
      });
      console.log(new p2('小猪课堂'));

      // defineProperty

      const p3 = new Proxy(
        {},
        {
          /**
           * @param target 源目标对象,也就是被代理的对象
           * @param property 监听的对象的属性名
           * @param desc defineProperty 第三个参数列表
           * **/
          defineProperty(target, property, desc) {
            return true;
          },
        }
      );

      Object.defineProperty(p3, 'a', {
        configurable: true,
        enumerable: true,
        value: 10,
      });

      // deleteProperty
      const p4 = new Proxy(
        {},
        {
          /**
           * @param target 源目标对象
           * @param property 被删除的属性名
           * **/
          deleteProperty(target, property) {
            console.log('被删除的属性', property);
          },
        }
      );

      delete p4.a;

      // get
      const p5 = new Proxy(
        {
          name: 'zhangsan',
        },
        {
          /**
           * @param target 源目标对象
           * @param property 属性名
           * @param receiver Proxy 或者继承 Proxy 的对象 也就是当前的 p5
           * **/
          get(target, property, receiver) {
            console.log('属性名：', property); // 属性名：name
            console.log('receiver', receiver); // Proxy {}
            console.log('target', target);
            return '小猪课堂';
          },
        }
      );

      console.log(p5.name);

      // set
      const p6 = new Proxy(
        {},
        {
          /**
           * @param target 源目标对象
           * @param property 将要被设置的属性名
           * @param value 新的属性值
           * @param receiver Proxy 或者继承 Proxy 的对象 也就是当前的 p6
           * **/
          set(target, property, value, receiver) {
            target[property] = value;
            console.log('property set: ' + property + ' = ' + value); // property set: a = 10
            return true;
          },
        }
      );
      p6.a = '10';

      // 还有一些其他配置,可以查看 https://zhuanlan.zhihu.com/p/524125274

      const obj1 = { name: 'zhangsan', age: 20 };
      const obj2 = Object.setPrototypeOf(obj1, { name: 'lisi', age: 10 });
      console.log(obj1 === obj2);
    </script>
  </body>
</html>
